Skip to content

feat: hex color strings for directive color fields - #146

Open
natemoo-re wants to merge 4 commits into
mainfrom
feat/hex-colors
Open

natemoo-re wants to merge 4 commits into
mainfrom
feat/hex-colors

Conversation

@natemoo-re

@natemoo-re natemoo-re commented Oct 11, 2026 •

Copy link
Copy Markdown
Member

Stacked on #139.

Implements support for CSS-styled hex color strings alongside rgba(). There's no C or wire format change, hex values are expanded to their rgba() equivalent at pack() time.

open("root", { bg: "#f80" })
text("hi", { color: "#ff8800aa" })

Supported hex grammar is

Form Meaning Alpha
#RGB digit d expands as d×17 (#f80 → #ff8800) 255
#RGBA 3-digit RGB + 1-digit alpha, expanded the same way (#f80a → #ff8800aa) from 4th digit
#RRGGBB standard RGB 255
#RRGGBBAA standard RGBA 2-digit alpha

… capability

Full-screen frames wrap in BSU/ESU when RuntimeCapabilities.syncOutput is
true; the flag rides reduce() per frame so a capability flip takes effect
on the next rendered frame with no invalidation signal. Zero-diff frames
emit zero bytes even when wrapped, and line mode is never wrapped.

Renderer-spec 7.9 discharges the deferral recorded in 7.8.
Color fields (open bg, border color/bg, border side color/bg, text
color/bg) accept a hex color string in addition to the packed ARGB
number. Hex grammar: '#' + exactly 3/4/6/8 hex digits, case-insensitive;
3/4-digit forms double each digit; missing alpha defaults to 255.
Conversion happens at the transfer-encoding boundary — hex strings never
appear on the wire; packed values are bit-identical to the equivalent
rgba() result. Invalid hex is invalid directive input: validate()
reports it and the packer MUST throw a TypeError before producing bytes.
Static types stay number | string; directive constructors check string
literals against the grammar at compile time (the TS equivalent of
#${string{3,4,6,8}}), reserving room for full CSS Color 4 syntax later.
Color fields (open bg, border color/bg, border side color/bg, text
color/bg) accept '#RGB', '#RGBA', '#RRGGBB', and '#RRGGBBAA' alongside
packed ARGB numbers. colorValue() expands strings at the transfer-
encoding boundary (RRGGBBAA digit order -> AARRGGBB word layout, 3/4-
digit forms double each digit, missing alpha = 255); the wire format
and the C renderer are untouched. Directive constructors type-check
string literals against the grammar via per-character recursion — a
flat template union is unrepresentable (TS2590) at 6/8 digits — while
computed strings pass through and are checked normatively by validate()
and the packer. Invalid hex throws TypeError before any bytes are
produced.
@bombshell-cooper

bombshell-cooper Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Changeset suggestion

The current changeset no longer matches this PR. This review contains a corrected replacement.

Why: Changeset should start with an approved active present-tense verb. Changeset package scope does not match the affected packages confidently.

View the proposed changeset
---
'@bomb.sh/tty': minor
---

Adds CSS-style hex color strings as an alternative to `rgba()` packed numbers for every color field.

`open({ bg })`, `border.color`, `border.bg`, per-side `color`/`bg`, and `text({ color, bg })` now accept `#RGB`, `#RGBA`, `#RRGGBB`, or `#RRGGBBAA` strings (case-insensitive, `#` required). Strings are expanded to their packed ARGB value at the transfer-encoding boundary; the wire format and renderer are unchanged.

Invalid hex strings are rejected by `validate()` and throw a `TypeError` from the packer before any bytes are produced. String literals are checked against the hex grammar at compile time — an invalid hex literal is a TypeScript type error at the call site.

#### Migration

This release changes the `Color` type accepted by color fields from `number` to `number | string`. Existing numeric `rgba()` usage is unaffected.

```diff
- open("box", { bg: rgba(255, 136, 0) })
+ open("box", { bg: "#ff8800" })   // hex string — or keep rgba(), both work
```

Review this changeset manually

If this draft is correct, react with 🚀 and Cooper will commit it to this branch.

@@ -0,0 +1,13 @@
---

@bombshell-cooper bombshell-cooper Bot Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changeset needs revision.

Changeset should start with an approved active present-tense verb. Changeset package scope does not match the affected packages confidently.

View the proposed replacement
---
'@bomb.sh/tty': minor
---

Adds CSS-style hex color strings as an alternative to `rgba()` packed numbers for every color field.

`open({ bg })`, `border.color`, `border.bg`, per-side `color`/`bg`, and `text({ color, bg })` now accept `#RGB`, `#RGBA`, `#RRGGBB`, or `#RRGGBBAA` strings (case-insensitive, `#` required). Strings are expanded to their packed ARGB value at the transfer-encoding boundary; the wire format and renderer are unchanged.

Invalid hex strings are rejected by `validate()` and throw a `TypeError` from the packer before any bytes are produced. String literals are checked against the hex grammar at compile time — an invalid hex literal is a TypeScript type error at the call site.

#### Migration

This release changes the `Color` type accepted by color fields from `number` to `number | string`. Existing numeric `rgba()` usage is unaffected.

```diff
- open("box", { bg: rgba(255, 136, 0) })
+ open("box", { bg: "#ff8800" })   // hex string — or keep rgba(), both work
```

@github-actions

github-actions Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

Size Increased — +2.1 KB

131.6 KB unpacked

@pkg-pr-new

pkg-pr-new Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@bomb.sh/tty@146

commit: 50f5673

@natemoo-re
natemoo-re marked this pull request as ready for review October 12, 2026 01:07
Base automatically changed from feat/sync-output to main October 19, 2026 11:58
# Conflicts:
#	.changeset/sync-output-capability.md
#	src/clayterm.c
#	src/clayterm.h
#	term-native.ts
#	term.ts
#	test/term.test.ts
#	test/width.test.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant